#pragma once
#include <opencv4/opencv2/opencv.hpp>
#include <string>
#include <fstream>
#include <iostream>
#include<map>
#include <dirent.h>
#include<unistd.h>
#include<yaml-cpp/yaml.h>
using namespace std;
using namespace cv;

// #define CV
//#define FISHEYE

class CCalibration
{
public:
    CCalibration(string patternImgPath, 
        string imagePath,string resultYaml, 
        Size boardSize,string suffix,
        int squareSizes,
        string calibResultPath="camera_result_detail.txt",
        string cameraType = "CV",
        bool outputDetail = false,
        bool downsampling = false,
        bool isDraw = false)  
    {
        this->patternImgPath = patternImgPath;
        this->iamge_path = imagePath;
        this->calibResultYaml = resultYaml;
        this->calibResultPath = calibResultPath;
        this->boardSize = boardSize;
        this->suffix = suffix;
        this->square_size = squareSizes;
        this->camera_type = cameraType;
        this->output_detail = outputDetail;
        this->downsampling = downsampling;
        this->is_draw = isDraw;
    }
    ~CCalibration() {}
    //日志相关
    static std::ofstream calibrationLog;
    static void InitLogFile(const std::string& filename);
    static void Log(const std::string& message);
    static void CloseLogFile();
private:
    vector<cv::Point3f> singlePatternPoints;
    vector<Mat> patternImgList;
    int imgHeight;//图片高
    int imgWidth;//图片宽
    int imgNum;//图片处理数量
    int square_size;//方格尺寸
    float scale = 0.25;//降采样参数
    float errThresh = 3000;//误差阈值
    string patternImgPath;//匹配图片路径
    string iamge_path;//记录处理图片路径的文件
    string calibResultPath;//详细结果输出文件
    string calibResultYaml;//内参输出
    string suffix = "jpg";//识别图片后缀
    string camera_type = "CV";//测定相机类型
    bool output_detail = false;//是否详细数值输出
    bool downsampling = false;//是否进行降采样
    bool is_draw = false;//是否显示绘制
    Size boardSize;//棋盘行列方格数
    Mat camK; //内参矩阵
    Mat camDiscoeff;//畸变矩阵
    std::map<int,std::pair<double,double>> errmap;//每幅图像的平均误差,最大投影误差
    double avg_err=0.0;//平均误差

private:
    //评定
    int evaluateCalibrationResult(vector<vector<cv::Point3f>> objectPoints, vector<vector<cv::Point2f>> cornerSquare, vector<int> pointCnts, vector<cv::Vec3d> _rvec,
        vector<cv::Vec3d> _tvec, cv::Mat _K, cv::Mat _D, int count, vector<int> &outLierIndex, int errThresh);
    bool testCorners(vector<cv::Point2f>& corners, int patternWidth, int patternHeight);
    void init3DPoints(cv::Size boardSize, cv::Size squareSize, vector<cv::Point3f> &singlePatternPoint);
public:
    bool writeParamsYaml();
    bool writeParamsTxt();
    bool readPatternImg();
    void calibProcess();
    void run();
};

